﻿namespace ImageProcessing
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using ShapesLib;
using System.Drawing;

    /// <summary>
    /// all operation on shaps drawed
    /// </summary>
    public class ShapeDraw
    {
        /// <summary>
        /// all shapes drawing
        /// </summary>
        private List<Shape> allShapes = new List<Shape>();

        /// <summary>
        /// shape To Be Drawn
        /// </summary>
        private SHAPENAME shapeToBeDrawn = SHAPENAME.NONE;

        /// <summary>
        /// selectedShape by user
        /// </summary>
        private Shape selectedShape = null;

        /// <summary>
        /// first point mouse click in x
        /// </summary>
        private int firstPointX;

        /// <summary>
        /// firstPoint click in Y
        /// </summary>
        private int firstPointY;

        /// <summary>
        /// lage for mouse down
        /// </summary>
        private bool mouseDown = false;

        /// <summary>
        /// temp shep for all operation
        /// </summary>
        private Shape tmpShape = null;

        /// <summary>
        /// image of this shaps
        /// </summary>
        private DImage myimage;

        /// <summary>
        /// Gets or sets all shapes.
        /// </summary>
        /// <value>
        /// All shapes.
        /// </value>
        public List<Shape> AllShapes
        {
            get { return this.allShapes; }
            set { this.allShapes = value; }
        }

        /// <summary>
        /// Gets or sets the selected shape.
        /// </summary>
        /// <value>
        /// The selected shape.
        /// </value>
        public Shape SelectedShape
        {
            get { return this.selectedShape; }
            set { this.selectedShape = value; }
        }

        /// <summary>
        /// Gets or sets the TMP shape.
        /// </summary>
        /// <value>
        /// The TMP shape.
        /// </value>
        public Shape TmpShape
        {
            get { return this.tmpShape; }
            set { this.tmpShape = value; }
        }

        /// <summary>
        /// Gets or sets the shape to be drawn.
        /// </summary>
        /// <value>
        /// The shape to be drawn.
        /// </value>
        public SHAPENAME ShapeToBeDrawn
        {
            get { return this.shapeToBeDrawn; }
            set { this.shapeToBeDrawn = value; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ShapeDraw"/> class.
        /// </summary>
        /// <param name="image">The image.</param>
        public ShapeDraw()
        {
           // this.myimage = image;
        }

        /// <summary>
        /// Mouses down action.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseDownAction(object sender, MouseEventArgs e)
        {
            this.mouseDown = true;
            this.firstPointX = e.X;
            this.firstPointY = e.Y;

            if (this.shapeToBeDrawn == SHAPENAME.NONE)
            {
                this.selectedShape = null;
                for (int i = 0; i < this.allShapes.Count; i++)
                {
                    if (this.allShapes[i].PointInShape(e.X, e.Y))
                    {
                        this.selectedShape = this.allShapes[i];
                    }
                }
            }
            else
            {
                int initialDimention = 2;
                switch (this.shapeToBeDrawn)
                {
                    case SHAPENAME.RECTANGLE:
                        this.tmpShape = new ShapesLib.Rectangle(this.firstPointX, this.firstPointX, initialDimention, initialDimention);
                        break;
                    case SHAPENAME.ELLIPSE:
                        this.tmpShape = new Ellipse(this.firstPointX, this.firstPointX, initialDimention, initialDimention);
                        break;
                    case SHAPENAME.CIRCLE:
                        int radius = initialDimention / 2;
                        this.tmpShape = new Circle(this.firstPointX, this.firstPointY, radius);
                        break;
                    default:
                        return;
                }
            }
        }

        /// <summary>
        /// Mouses the move action.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseMoveAction(object sender, MouseEventArgs e)
        {
            if (!this.mouseDown)
            {
                return;
            }

            if (this.shapeToBeDrawn == SHAPENAME.FreeMove)
            {
                if (this.tmpShape == null)
                {
                    this.tmpShape = new ShapesLib.Polygon();
                }

                ((Polygon)this.tmpShape).AddPoint(e.Location); // Invalidate();
            }

            if (this.shapeToBeDrawn == SHAPENAME.NONE)
            {
                if (this.selectedShape != null)
                {
                    int deltaX = e.X - this.firstPointX;
                    int deltaY = e.Y - this.firstPointY;
                    this.selectedShape.Translate(deltaX, deltaY);
                    this.firstPointX = e.X;
                    this.firstPointY = e.Y;
                }
            }
            else
            {
                int topLeftX = 0, topLeftY = 0, width = 0, height = 0;
                this.GetBoundingBox(this.firstPointX, this.firstPointY, e.X, e.Y, ref topLeftX, ref topLeftY, ref width, ref height);

                switch (this.shapeToBeDrawn)
                {
                    case SHAPENAME.RECTANGLE:
                        this.tmpShape.X = topLeftX;
                        this.tmpShape.Y = topLeftY;
                        ((ShapesLib.Rectangle)this.tmpShape).Width = width;
                        ((ShapesLib.Rectangle)this.tmpShape).Height = height;
                        break;
                    case SHAPENAME.ELLIPSE:
                        this.tmpShape.X = topLeftX;
                        this.tmpShape.Y = topLeftY;
                        ((ShapesLib.Ellipse)this.tmpShape).R1 = width;
                        ((ShapesLib.Ellipse)this.tmpShape).R2 = height;
                        break;
                    case SHAPENAME.CIRCLE:
                        int radius = (int)Math.Sqrt(Math.Pow(e.X - this.firstPointX, 2) + Math.Pow(e.Y - this.firstPointY, 2));
                        this.tmpShape.X = this.firstPointX;
                        this.tmpShape.Y = this.firstPointY;
                        ((ShapesLib.Circle)this.tmpShape).Radius = radius;
                        break;
                    default:
                        return;
                }
            }
        }

        /// <summary>
        /// Mouses up action.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseUpAction(object sender, MouseEventArgs e)
        {
            if (!this.mouseDown)
            {
                return;
            }

            if (this.shapeToBeDrawn == SHAPENAME.FreeMove)
            {
                if (this.tmpShape == null)
                {
                    return;
                }

                this.allShapes.Add(this.tmpShape);
                this.tmpShape = null;

                this.shapeToBeDrawn = SHAPENAME.NONE;
                return;
            }

            this.mouseDown = false;

            if (this.shapeToBeDrawn != SHAPENAME.NONE && this.shapeToBeDrawn != SHAPENAME.POLYGON)
            {
                this.allShapes.Add(this.tmpShape);
                
                this.tmpShape = null;
            }
        }

        /// <summary>
        /// Mouses the click action.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseClickAction(object sender, MouseEventArgs e)
        {
            if (this.shapeToBeDrawn == SHAPENAME.POLYGON)
            {
                if (this.tmpShape == null)
                {
                    this.tmpShape = new ShapesLib.Polygon();
                }

                ((Polygon)this.tmpShape).AddPoint(e.Location);

                // Invalidate();
            }
        }

        /// <summary>
        /// Mouses the double click action.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseDoubleClickAction(object sender, MouseEventArgs e)
        {
            if (this.shapeToBeDrawn == SHAPENAME.POLYGON)
            {
                if (this.tmpShape == null)
                {
                    return;
                }

                Shape t = new Polygon();
                t = this.tmpShape;
                this.allShapes.Add(t);
                this.tmpShape = null;
            }
        }

        /// <summary>
        /// Gets the bounding box.
        /// </summary>
        /// <param name="firstPtX">The first pt X.</param>
        /// <param name="firstPtY">The first pt Y.</param>
        /// <param name="secondPtX">The second pt X.</param>
        /// <param name="secondPtY">The second pt Y.</param>
        /// <param name="topleftX">The topleft X.</param>
        /// <param name="topleftY">The topleft Y.</param>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        public void GetBoundingBox(int firstPtX, int firstPtY, int secondPtX, int secondPtY, ref int topleftX, ref int topleftY, ref int width, ref int height)
        {
            width = Math.Abs(secondPtX - firstPtX);
            height = Math.Abs(secondPtY - firstPtY);

            topleftX = firstPtX;
            if (secondPtX < topleftX)
            {
                topleftX = secondPtX;
            }

            topleftY = firstPtY;
            if (secondPtY < topleftY)
            {
                topleftY = secondPtY;
            }
        }

        /// <summary>
        /// Changes the color tool strip menu item action.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        /// <param name="colorDialog1">The color dialog1.</param>
        public void ChangeColorToolStripMenuItemAction(Color newcolor)
        {
            if (this.selectedShape == null)
            {
                MessageBox.Show("Please select a shape first!");
                return;
            }

             this.selectedShape.FillColor = newcolor; // Invalidate();
        }

        /// <summary>
        /// Scales the shape action.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        /// <param name="txtScaleFactor">The TXT scale factor.</param>
        public void ScaleShapeAction(string txtScaleFactor)
        {
            if (this.selectedShape == null)
            {
                MessageBox.Show("Please select a shape first!");
                return;
            }

            if (txtScaleFactor == string.Empty)
            {
                MessageBox.Show("Please Enter Scale Factor !");
                return;
            }

            if (txtScaleFactor != string.Empty)
            {
                this.selectedShape.Scale(Convert.ToDouble(txtScaleFactor));
            }
            Main.Instance.Invalidate();
        }
    }
}
